package CI.aufgabe2.cip.mynodes;

import CI.aufgabe2.cip.SymbolTable;
import CI.aufgabe2.cip.base.AbstractDescr;

public class MyProcedureBodyNode extends MyAbstractNode {

	private static final long serialVersionUID = 1L;
	
	private final MyDeclarationsNode declarations;
	private final MyStatementSequenceNode statementSeq;
    private final int linkage = 3;
    private int allocatedMemory;
	
	public MyProcedureBodyNode(MyDeclarationsNode declarations, MyStatementSequenceNode statementSeq) {
		this.declarations=declarations;
		this.statementSeq=statementSeq;
	}

	@Override
	public void print() {
		trace("ProcedureBodyNode ");
		if(declarations != null)
			declarations.print();
		
		if(statementSeq != null)
			statementSeq.print();
		
		unindent();

	}
	
	public int getAllocatedMemory(){
		return this.allocatedMemory;
	}
	
	public AbstractDescr compile(SymbolTable sym) {
		
		if(declarations!=null)
			declarations.compile(sym);
		this.allocatedMemory = linkage + sym.getSize();
		//entry Code starts here
//		write("INIT, " + allocatedMemory);
//		write("LABEL, " + label);
		write("PUSHREG, RK");
		write("PUSHREG, FP");
		
		
		//SL Register retten
		write("PUSHI, " + sym.currentLvl());
		write("PUSHREG, SL");
		
		
		//FP := SP
		write("GETSP");
		write("SETFP");
		
		
		//SL := FP
		write("GETFP");
		write("PUSHI, " + sym.currentLvl());
		write("SETSL");
		
		
		//SP := SP + lokale variablen
		write("GETSP");
		write("PUSHI, " + sym.getSize());
		write("ADD");
		write("SETSP");
		//end of entryCode
		
		
		if(statementSeq != null){
			statementSeq.compile(sym);
		}
		
		//exitCode starts here
		//SP := FP
		write("GETFP");
		write("SETSP");
		
		
		//Restore SL
		write("PUSHI, " + sym.currentLvl());
		write("POPREG, SL");
		write("POPREG, FP");
		write("POPREG, RK");
		return null;
	}
	public AbstractDescr compileL(SymbolTable sym,int label) {
		if(declarations!=null)
			declarations.compile(sym);
		this.allocatedMemory = linkage + sym.getSize();
		//entry Code starts here
//		write("INIT, " + allocatedMemory);
		write("LABEL, " + label);
		write("PUSHREG, RK");
		write("PUSHREG, FP");
		
		
		//SL Register retten
		write("PUSHI, " + sym.currentLvl());
		write("PUSHREG, SL");
		
		
		//FP := SP
		write("GETSP");
		write("SETFP");
		
		
		//SL := FP
		write("GETFP");
		write("PUSHI, " + sym.currentLvl());
		write("SETSL");
		
		
		//SP := SP + lokale variablen
		write("GETSP");
		write("PUSHI, " + sym.getSize());
		write("ADD");
		write("SETSP");
		//end of entryCode
		
		
		if(statementSeq != null){
			statementSeq.compile(sym);
		}
		
		//exitCode starts here
		//SP := FP
		write("GETFP");
		write("SETSP");
		
		
		//Restore SL
		write("PUSHI, " + sym.currentLvl());
		write("POPREG, SL");
		write("POPREG, FP");
		write("POPREG, RK");
		return null;
	}
}
